#include <hd_oled.h>
#include <pd_gpio.h>
#include <pd_i2c_hd.h>
#include <hd_oled_protocol_i2c.h>
#include <delay.h>
#include "main.h"

#define ARRAY_SIZE(x)       sizeof(x) / sizeof(x[0])
#define USE_HARDWARE_SPI    1
#define USE_HARDWARE_I2C    1
OLED oled;

extern void SystemClock_Config(void);

void SystemClock_Config_84MHz(void);

void oled_instance(OLED *oled);


int main(void) {

//    SystemClock_Config();
    SystemClock_Config_84MHz();

    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

    oled_instance(&oled);

    OLED_printf(&oled, 0, 0, "SYSCLK:");
    OLED_printf(&oled, 56, 0, "%09d", SystemCoreClock);

    while (1) {
        OLED_printf(&oled, 0, 16, "Running");
        OLED_refresh(&oled);

        delay_ms(500);

        OLED_printf(&oled, 0, 16, "       ");
        OLED_refresh(&oled);
        delay_ms(500);
    }

}


/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config_84MHz(void) {
    LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
    while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2);
    LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
    LL_RCC_HSI_SetCalibTrimming(16);
    LL_RCC_HSI_Enable();

    /* Wait till HSI is ready */
    while (LL_RCC_HSI_IsReady() != 1);
    LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLLM_DIV_8, 84, LL_RCC_PLLP_DIV_2);
    LL_RCC_PLL_Enable();

    /* Wait till PLL is ready */
    while (LL_RCC_PLL_IsReady() != 1);
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
    LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
    LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

    /* Wait till System clock is ready */
    while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL);
    LL_Init1msTick(84000000);
    LL_SetSystemCoreClock(84000000);
}


void oled_instance(OLED *oled) {
    // I2C gpio init
    static GPIO oledSckGPIO, oledSdaGPIO;
    GPIO_constructor(&oledSckGPIO, GPIOB, LL_GPIO_PIN_10); // I2Cx_SCK
    GPIO_constructor(&oledSdaGPIO, GPIOB, LL_GPIO_PIN_11); // I2Cx_SDA

#ifdef USE_HARDWARE_I2C
    static I2CHardware i2c2;
    I2CHardware_constructor(&i2c2, I2C2, &oledSckGPIO, &oledSdaGPIO);
#elif USE_SIMULATE_I2C
    static I2CSimulate i2c2;
    I2CSimulate_constructor(&i2c2, &oledSckGPIO, &oledSdaGPIO);
#endif
    I2C_init((I2C *) &i2c2);

    // OLED protocol of I2C
    static OLEDProtocolI2C oledProtocolI2c;
    OLEDProtocolI2C_constructor(&oledProtocolI2c, (I2C *) &i2c2);

    // OLED font instance.
    static OLEDFont oledFont;
    OLEDFont_contructor(&oledFont, NULL);

    // OLED instance of 4-PIN(I2C)
    OLED_constructor(oled, (OLEDProtocol *) &oledProtocolI2c, &oledFont);

    OLED_init(oled);

    OLED_clear(oled);
    OLED_refresh(oled);
}
